/*
	PlAr is Platform Arena: a 2D multiplayer shooting game
	Copyright (c) 2010, Antonio Ragagnin <spocchio@gmail.com>
    All rights reserved.

    This file is licensed under the New BSD License.
 */

package plar.core;

import java.util.ArrayList;
import java.util.List;

import org.jbox2d.collision.AABB;
import org.jbox2d.collision.shapes.PolygonShape;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.BodyDef;
import org.jbox2d.dynamics.BodyType;
import org.jbox2d.dynamics.Fixture;
import org.jbox2d.dynamics.FixtureDef;

import plar.core.Element;
import plar.core.ActionTimer;

/**
 * Define the basic functions of character, the guns, manage the keyboard input.
 *
 * @author Antonio Ragagnin
 *
 */
public class ElementPlayer extends Element {


    /**
	* the list of guns aviable the player.
	*/
    public List<Gun> gl;
	
	/**
	* the chat username
	*/
    public String username;
	
	/**
	* the x direction of the mouse
	*/
    public float directionX;
	/**
	* the y direction of the mouse
	*/
    public float directionY;
	/**
	* running direction
	*/
    public int isRunning=0;
    /**
	* times the player is killed by someone, do not modify
	*/
    public int killed=0;
    /**
	* times the player killed someone,do not modify
	*/
    public int kills=0;
	/**
	* the duration of the jump, needed by the class to decide how much time leave the jumping sprite on
	*/
    public float jumpTime=0.1f;
	
	/**
	* the life of the player
	*/
    public float energy;
	
	/**
	* current gun
	*/
    public int currentGunIndex;
	
	/**
	* the path of an image that represent the player.
	*/
    public String presentation;
	/**
	* is true if the player is firing, used by the sprite manager 
	*/
    public boolean isFiring = false;
	/**
	* is true if the player is jumping, used by the sprite manager 
	*/
    public boolean isJumping = false;
 	/**
	* is true if the player is bended down
	*/
   public boolean isBending = false;

   /**
	* the speed of running
	*/
    public float runSpeed;
	/**
	* the vertical speed made by a jumping
	*/
    public float jumpSpeed;
	
	/**
	* size after a bending down
	*/
    public Vec2 reducedSize;
	
	/**
	* size of the player
	*/
    public Vec2 standardSize;
	
	/**
	* name of the player, it define the kind of the character. it is NOT related to the username of the client.
	*/
    public String name;
	
	/**
	* a brief description of the element
	*/
    public String description;
	
	/**
	* save the last element he touched, used to know who killed who.
	*/
    public ElementPlayer lastTouch;
	
	/**
	* used to know how much time leave the fire sprite on.
	*/
    public float fireTime;
    private java.util.Random generator;
    public ElementPlayer() {
        super();

        type = Common.ElementType.PLAYER;
        isRunnable = true;
        username = new String();
        setStaticSprite("res/player.png");
        friction=10;

        jumpSpeed = 7f;
        runSpeed = 6f;

        reducedSize = new Vec2(0.3f, 0.35f);
        standardSize = new Vec2(0.3f, 0.7f);
        setBoxShape(standardSize.x, standardSize.y);
        fireTime=0.7f;
        ActionTimer at = new ActionTimer("",fireTime,0,true) {

            public Object force(Object o)
            {

                ((ElementPlayer)me).isFiring=false;

                active=false;
                return null;

            }
        };
        ActionTimer jt = new ActionTimer("",jumpTime,0,true) {

            public Object force(Object o)
            {

                active=((ElementPlayer)me).isJumping=((ElementPlayer)me).isOnAir();
                //	Common.info(1,"jumpin:"+((ElementPlayer)me).isJumping);


                return null;

            }
        };

        at.active=false;
        actions.addAction("input", new ActionUserInput());
        actions.addAction("firetime", at);
        actions.addAction("jumptime", jt);

        actions.addAction("status", new ActionCharacterStatus());
        gl = new ArrayList<Gun>();
        generator = new java.util.Random();

    }

    public void setBodyDef(BodyDef bd)
    {
        bd.type = BodyType.DYNAMIC;

    }
    public void setBody(Body b)
    {
        super.setBody(b);
        body.setLinearDamping(0f);


    }



    public void input(KeyFlag k) {



        isJumping = isOnAir();

        float hSpeed=runSpeed;
        /*if (isJumping)
        	hSpeed = airySpeed;
        else
        	hSpeed = runSpeed;
        */
        if (k.check(KeyFlag.LEFT))
        {
            //this.setSpeed(new Vec2(-hSpeed, generator.nextFloat() ));

            this.setSpeed(new Vec2(-hSpeed, 0f));
            if(!isJumping) this.applySpeed(new Vec2(0f, (generator.nextFloat()-0.5f) *0.5f));
			if(isRunning!=-1)            this.directionX=-1;
			
			 isRunning = -1;
        }
        if (k.check(KeyFlag.RIGHT))
        {
            //this.setSpeed(new Vec2(hSpeed, generator.nextFloat()));

            this.setSpeed(new Vec2(hSpeed, 0f));
            if(!isJumping) this.applySpeed(new Vec2(0f,(generator.nextFloat()-0.5f)*0.5f ));
			if(isRunning!=1)            this.directionX=1;
		
			isRunning = 1;
        }



        if (k.check(KeyFlag.JUMP) && !isJumping)
            this.setSpeed(new Vec2(0, -jumpSpeed));
        ((ActionTimer)actions.getAction("jumptime")).active=true;

        if (k.check(KeyFlag.FIRE))
        {

            this.gl.get(currentGunIndex).fire();
            k.del(KeyFlag.FIRE);
            isFiring=true;
            ((ActionTimer)actions.getAction("firetime")).active=true;

        }
        if (k.check(KeyFlag.SPECIAL)) {
            specialMove(k);
        }
        if (k.check(KeyFlag.DOWN) && !isJumping ||(!k.check(KeyFlag.DOWN) && isBending)) {
            Vec2 oldPos = getPosition().clone();
            Vec2 oldSize = getSize().clone();
            Vec2 newPos =  new Vec2();
            Vec2 newSize = new Vec2();

            //	Common.info(1,"DOWN: oldPOS="+getPosition()+" oldSIZE="+getSize());
            PolygonShape newShape = new PolygonShape();

            //bodydef = new BodyDef();
            //level.delElement(this);
            if (isBending) {
                newPos = new Vec2(oldPos.x, oldPos.y + oldSize.y / 2f- standardSize.y / 2);
                newSize = new Vec2(standardSize.x, standardSize.y);
                isBending = false;
            } else {

                newPos = new Vec2(oldPos.x, oldPos.y + oldSize.y / 2f - reducedSize.y	/ 2);
                newSize = new Vec2(reducedSize.x, reducedSize.y);
                isBending = true;

            }
            //	Common.info(1,"DOWN: oldPOS="+getPosition()+" oldSIZE="+getSize());


            body.setTransform(newPos,0f);

            body.destroyFixture(body.getFixtureList());
            //body.resetMassData();
            //FixtureDef fd = new FixtureDef();
            setBoxShape(newSize.x, newSize.y);
            //fd.shape=shape;
            //body.createFixture(fd);
            //setFixture(body.createFixture(fd));
            setBody(body);
            updateAABB();

            k.del(KeyFlag.DOWN);
        }

        if (k.number()!=0) {
            int n=k.number()-1;
            if(gl.get(n)!=null)			currentGunIndex=n;
        }


        if (k.Key == KeyFlag.NONE)
        {
            allKeysReleased();
            applySpeed(new Vec2(-getSpeed().x,0));
			 isRunning = 0;
        }

        //Common.info(1,"bodu:"+body.isActive()+" mass:"+body.getMass()+ " waawakw"+body.isAwake());
    }

    public void allKeysReleased() {

    }

    public void specialMove(KeyFlag k) {

    }

    private boolean isOnAir() {
        AABB r = new AABB(getAABB());
        r.lowerBound.x=0f;
        r.upperBound.x=0f;
        r.lowerBound.x += body.getPosition().x;
        r.lowerBound.y += body.getPosition().y+0.2f;
        r.upperBound.x += body.getPosition().x;
        r.upperBound.y += body.getPosition().y;


        ArrayList<Fixture> af=Common.queryAABB(level.world, r);
        //Common.info(7, " is it jumping?" + af.size());
        return (af.size() == 1);
        //return false;
    }

    public void initComponents() {

    }

}
